{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "b1172161",
   "metadata": {},
   "source": [
    "## 固定示例\n",
    "\n",
    "最基本（也是常见）的小样本提示技术是使用固定提示示例。这样您就可以选择一条链条，对其进行评估，并避免担心生产中的额外移动部件。\n",
    "\n",
    "模板的基本组件是： \n",
    "- examples ：要包含在最终提示中的字典示例列表。 \n",
    "- example_prompt ：通过其 format_messages 方法将每个示例转换为 1 条或多条消息。一个常见的示例是将每个示例转换为一条人工消息和一条人工智能消息响应，或者一条人工消息后跟一条函数调用消息。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "a1109435",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.prompts import (\n",
    "    ChatPromptTemplate,\n",
    "    FewShotChatMessagePromptTemplate,\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "0c1385f2",
   "metadata": {},
   "outputs": [],
   "source": [
    "examples = [\n",
    "    {\"input\": \"2+2\", \"output\": \"4\"},\n",
    "    {\"input\": \"2+3\", \"output\": \"5\"},\n",
    "]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "160691f2",
   "metadata": {},
   "source": [
    "组装成少示例的提示模板。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "8dcd8698",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Human: 2+2\n",
      "AI: 4\n",
      "Human: 2+3\n",
      "AI: 5\n"
     ]
    }
   ],
   "source": [
    "# This is a prompt template used to format each individual example.\n",
    "example_prompt = ChatPromptTemplate.from_messages(\n",
    "    [\n",
    "        (\"human\", \"{input}\"),\n",
    "        (\"ai\", \"{output}\"),\n",
    "    ]\n",
    ")\n",
    "few_shot_prompt = FewShotChatMessagePromptTemplate(\n",
    "    example_prompt=example_prompt,\n",
    "    examples=examples,\n",
    ")\n",
    "\n",
    "print(few_shot_prompt.format())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "320b50bc",
   "metadata": {},
   "outputs": [],
   "source": [
    "#最后，组装最终的提示并将其与模型一起使用。\n",
    "\n",
    "final_prompt = ChatPromptTemplate.from_messages(\n",
    "    [\n",
    "        (\"system\", \"你是一位非常厉害的数学天才。\"),\n",
    "        few_shot_prompt,\n",
    "        (\"human\", \"{input}\"),\n",
    "    ]\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "e75cc106",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'9'"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain_core.output_parsers import StrOutputParser\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "from langchain_openai import ChatOpenAI\n",
    "openai_api_key = \"EMPTY\"\n",
    "openai_api_base = \"http://127.0.0.1:1234/v1\"\n",
    "chat = ChatOpenAI(\n",
    "    openai_api_key=openai_api_key,\n",
    "    openai_api_base=openai_api_base,\n",
    "    temperature=0.7,\n",
    ")\n",
    "\n",
    "output_parser = StrOutputParser()\n",
    "\n",
    "chain = final_prompt | chat | output_parser\n",
    "\n",
    "chain.invoke({\"input\":\"3的平方是多少？\"})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "6d914c13",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='我们知道，一个数的平方是它和其本身的乘积。所以，3的平方就是3乘以3，即3*3=9。')"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chat.invoke(input=\"3的平方是多少？\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8c689a03",
   "metadata": {},
   "source": [
    "## 动态几次提示\n",
    "\n",
    "有时您可能希望根据输入来限制显示哪些示例。为此，您可以将 examples 替换为 example_selector 。其他组件与上面相同！回顾一下，动态几次提示模板将如下所示：\n",
    "\n",
    "- example_selector ：负责为给定输入选择少数样本（以及它们返回的顺序）。它们实现了 BaseExampleSelector 接口。一个常见的例子是向量存储支持的 SemanticSimilarityExampleSelector\n",
    "\n",
    "- example_prompt ：通过其 format_messages 方法将每个示例转换为 1 条或多条消息。一个常见的示例是将每个示例转换为一条人工消息和一条人工智能消息响应，或者一条人工消息后跟一条函数调用消息。\n",
    "\n",
    "这些可以再次与其他消息和聊天模板组合以组合您的最终提示。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "149edc51",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\a4154\\AppData\\Roaming\\Python\\Python310\\site-packages\\transformers\\utils\\hub.py:124: FutureWarning: Using `TRANSFORMERS_CACHE` is deprecated and will be removed in v5 of Transformers. Use `HF_HOME` instead.\n",
      "  warnings.warn(\n",
      "d:\\ProgramData\\anaconda3\\lib\\site-packages\\torch\\_utils.py:776: UserWarning: TypedStorage is deprecated. It will be removed in the future and UntypedStorage will be the only storage class. This should only matter to you if you are using storages directly.  To access UntypedStorage directly, use tensor.untyped_storage() instead of tensor.storage()\n",
      "  return self.fget.__get__(instance, owner)()\n"
     ]
    }
   ],
   "source": [
    "from langchain_community.embeddings.huggingface import HuggingFaceEmbeddings\n",
    "\n",
    "embeddings_path = \"D:\\\\ai\\\\download\\\\bge-large-zh-v1.5\"\n",
    "embeddings = HuggingFaceEmbeddings(model_name=embeddings_path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "d31d219b",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.prompts.example_selector import SemanticSimilarityExampleSelector\n",
    "from langchain_community.vectorstores import Chroma\n",
    "examples = [\n",
    "    {\"input\": \"2+2\", \"output\": \"4\"},\n",
    "    {\"input\": \"2+3\", \"output\": \"5\"},\n",
    "    {\"input\": \"2+4\", \"output\": \"6\"},\n",
    "    {\"input\": \"牛对月亮说了什么？\", \"output\": \"什么都没有\"},\n",
    "    {\n",
    "        \"input\": \"给我写一首关于月亮的五言诗\",\n",
    "        \"output\": \"月儿挂枝头，清辉洒人间。 银盘如明镜，照亮夜归人。 思绪随风舞，共赏中秋圆。\",\n",
    "    },\n",
    "]\n",
    "\n",
    "to_vectorize = [\" \".join(example.values()) for example in examples]\n",
    "vectorstore = Chroma.from_texts(to_vectorize, embeddings, metadatas=examples)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "cda09c9a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'input': '牛对月亮说了什么？', 'output': '什么都没有'}, {'input': '2+2', 'output': '4'}]"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "example_selector = SemanticSimilarityExampleSelector(\n",
    "    vectorstore=vectorstore,\n",
    "    k=2,\n",
    ")\n",
    "\n",
    "# The prompt template will load examples by passing the input do the `select_examples` method\n",
    "example_selector.select_examples({\"input\": \"对牛弹琴\"})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "fde39281",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.prompts import (\n",
    "    ChatPromptTemplate,\n",
    "    FewShotChatMessagePromptTemplate,\n",
    ")\n",
    "\n",
    "# Define the few-shot prompt.\n",
    "few_shot_prompt = FewShotChatMessagePromptTemplate(\n",
    "    # The input variables select the values to pass to the example_selector\n",
    "    input_variables=[\"input\"],\n",
    "    example_selector=example_selector,\n",
    "    # Define how each example will be formatted.\n",
    "    # In this case, each example will become 2 messages:\n",
    "    # 1 human, and 1 AI\n",
    "    example_prompt=ChatPromptTemplate.from_messages(\n",
    "        [(\"human\", \"{input}\"), (\"ai\", \"{output}\")]\n",
    "    ),\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "deb6e49d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Human: 2+3\\nAI: 5\\nHuman: 2+4\\nAI: 6'"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "few_shot_prompt.format(input=\"What's 3+3?\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "da1a67e9",
   "metadata": {},
   "outputs": [],
   "source": [
    "final_prompt = ChatPromptTemplate.from_messages(\n",
    "    [\n",
    "        (\"system\", \"你是一位非常厉害的数学天才。\"),\n",
    "        few_shot_prompt,\n",
    "        (\"human\", \"{input}\"),\n",
    "    ]\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "df507c7d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "System: 你是一位非常厉害的数学天才。\n",
      "Human: 2+3\n",
      "AI: 5\n",
      "Human: 2+4\n",
      "AI: 6\n",
      "Human: 3+5是多少？\n"
     ]
    }
   ],
   "source": [
    "print(final_prompt.format(input=\"3+5是多少？\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "8a2ef964",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'8'"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain_core.output_parsers import StrOutputParser\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "from langchain_openai import ChatOpenAI\n",
    "openai_api_key = \"EMPTY\"\n",
    "openai_api_base = \"http://127.0.0.1:1234/v1\"\n",
    "chat = ChatOpenAI(\n",
    "    openai_api_key=openai_api_key,\n",
    "    openai_api_base=openai_api_base,\n",
    "    temperature=0.7,\n",
    ")\n",
    "\n",
    "output_parser = StrOutputParser()\n",
    "\n",
    "chain = final_prompt | chat | output_parser\n",
    "\n",
    "chain.invoke({\"input\":\"3+5是多少？\"})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c9c85a0f",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
